﻿// Inner Fire 游戏引擎库
// DirectX 渲染器主类
//
// Copyright (c) 2024 by 尔西大帝. All rights reserved.
//
// 用于DirectX的渲染器
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2024-11-29

#pragma once

#include <DirectXCollision.h>
#include <dx/core/dx_core.h>
#include <dx/core/dx_descriptor.h>
#include <dx/core/dx_pipeline.h>
#include <dx/core/dx_root_signature.h>
#include <dx/core/frame_resource.h>
#include <dx/graphics/dx_draw_desc.h>
#include <dx/mesh/dx_mesh.h>
#include <dx/mesh/geometry_generator.h>
#include <dx/mesh/gpu_waves.h>
#include <dx/mesh/render_item.h>
#include <dx/mesh/skin_animator.h>
#include <dx/mesh/tree_sprite.h>
#include <dx/texture/dx_material.h>
#include <dx/texture/dx_texture.h>
#include <dx/texture/render_target.h>
#include <dx/texture/shadow_map.h>
#include <dx/texture/sobel_filter.h>
#include <dx/texture/ssao.h>
#include <dx/texture/ui_depth_map.h>
#include <dx/ui/ui_mesh_manager.h>
#include <sprite_pack.h>
#include <xml_reader.h>

// 必然所属同一级的项目，所以不需要<>
#include "dx_draw.h"
#include "dx_initer.h"
#include "dx_lights.h"
#include "dx_pass.h"
#include "dx_post_processing.h"
#include "dx_shadows.h"
#include "dx_swapchain.h"
#include "dx_view.h"
#include "dx_frame_resource.h"
#include "dx_ui.h"
#include "dx_instanced_sprite.h"

namespace ifire::dx {
class DxMeshFactory;

class DxGraphics {
public:
  DxGraphics();
  DxGraphics(const DxGraphics&) = delete;
  DxGraphics& operator=(const DxGraphics&) = delete;
  ~DxGraphics();

  // 载入配置（需要先执行）
  void LoadConfig(const std::string filename);
  const ikit::XmlReader& Config() const { return config; }

  // 初始化DirectX
  void InitDirect3D(HWND hwnd, UINT width, UINT height);
  // 在窗口大小改变时调用
  void OnResize();
  // 初始化渲染管线
  void InitPipeline();
  // 更新项目
  void Update();
  // 每帧进行更新项目
  void FixedUpdate();
  // 每秒更新的项目（用于缓慢更新，比如文件检查）
  void UpdateSecond();
  // 进行绘制
  void Draw() { draw_.Draw(); }

  // 重置命令队列
  void ResetCommandList();
  // 执行完当前的指令
  void FlushCommandQueue() { initer_.FlushCommandQueue(); }
  // 将指令提交到队列并执行
  void ExecuteCommands();

  // 创建描述符堆，必须等待纹理载入完成之后才能执行。
  void BuildDescriptorHeaps();
  // 为纹理设置一个描述符堆
  void SetTextureDescriptor(DxTexture* texture);
  // 设置绘制项目
  void SetDrawDesc(const DxDrawDesc& desc);

  //
  // UI相关
  //
  // 创建一个UI文本
  DxText* CreateText(const DxTextDesc& desc, UIRenderItem* parent);
  // 创建一个UI图片
  DxImage* CreateImage(const DxImageDesc& desc, UIRenderItem* parent);
  // 创建一个UI布局容器
  DxLayout* CreateLayout(const DxLayoutDesc& desc, UIRenderItem* parent);

  // 处理输入
  void OnMouseDown(WPARAM btn_state, int x, int y);
  void OnMouseUp(WPARAM btn_state, int x, int y);
  void OnMouseMove(WPARAM btn_state, int x, int y);
  void OnMouseWheel(int delta);

  // 设置信息
  void Set4xMsaaState(bool enable);
  void SetClientSize(UINT width, UINT height) {
    view_.SetClientSize(width, height);
  }

  // 打印调试
  size_t PrintStatus(const char* format, ...);

  // 属性访问
  inline int GetWidth() const { return view_.GetWidth(); }
  inline int GetHeight() const { return view_.GetHeight(); }
  inline HWND GetHwnd() const { return hwnd_; }
  inline bool IsWireMode() const { return is_wire_mode_; }
  inline void SetWireMode(bool value) { is_wire_mode_ = value; }
  inline bool IsReady() const { return is_inited_; }
  inline bool IsSobelEnable() const {
    return post_processing_.GetSobelEnable();
  }
  inline DebugLayer GetDebugLayer() const { return show_debug_layer_; }
  inline float GetAspectRatio() const { return view_.GetAspectRatio(); }
  inline UIWidget GetClientWidget() const { return view_.GetClientWidget(); }
  inline XMFLOAT2 GetClientSize() const { return view_.GetClientSize(); };
  inline POINT GetLastMousePos() const { return last_mouse_pos_; }
  inline FrameResource* CurrentFrameRes() { return frame_res_.Current(); }
  inline ID3D12Device* Device() { return initer_.Device(); }
  inline IDXGIFactory4* GetFactory() { return initer_.GetFactory(); }
  inline ID3D12GraphicsCommandList* CommandList() { return initer_.CommandList(); }
  inline ID3D12CommandQueue* GetCmdQueue() { return initer_.GetCmdQueue(); }
  inline ID3D12CommandAllocator* GetAllocator() { return initer_.GetAllocator(); }
  inline ID3D12Fence* GetFence() { return initer_.GetFence(); }

  D3D12_CPU_DESCRIPTOR_HANDLE GetBackBufferView() const;
  ID3D12Resource* GetBackBuffer() const;
  D3D12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const;

  DxDescriptor& GetDescriptor() { return descriptor_; }
  DxRootSignature& GetRootsign() { return rootsign_; }
  DxPipeline& GetPipeline() { return pipeline_; }
  DxView& GetView() { return view_; }
  DxDraw& GetDraw() { return draw_; }
  DxIniter& GetIniter() { return initer_; }
  DxSwapchain& GetSwapchain() { return swapchain_; }
  DxPostProcessing& GetPostProcessing() { return post_processing_; }
  DxLights& GetLights() { return lights_; }
  DxShadows& GetShadows() { return shadows_; }
  DxPass& GetPass() { return pass_; }
  DxFrameResource& GetFrameRes() { return frame_res_; }
  DxUI& GetUI() { return ui_; }
  DxInstancedSprite& GetInstancedSprite() { return instanced_sprite_; }

  GpuWaves* GetWaves() { return waves_.get(); }
  RenderTarget* GetOffscreenRt() { return post_processing_.GetOffscreenRt(); }
  SobelFilter* GetSobel() { return post_processing_.GetSobel(); }
  Ssao* GetSsao() { return post_processing_.GetSsao(); }
  ShadowMap* GetShadow() { return shadows_.GetShadowMap(); }
  UIMeshManager* GetUIMesh() { return ui_.GetMesh(); }
  UIDepthMap* GetUIDepthMap() { return ui_.GetDepthMap(); }
  PassConstants& GetMainPass() { return pass_.GetMainPass(); }
  eastl::vector<RenderItemPtr>& Items() { return *draw_.GetDesc().items; }
  eastl::vector<dx::MaterialPtr>& Materials() {
    return *draw_.GetDesc().materials;
  }
  eastl::vector<SkinAnimatorPtr>& Animators() {
    return *draw_.GetDesc().animators;
  }

public:
  char mCaption[256];
  char mStatus[256];

private:
  //
  // 初始化相关
  //
  void EnableDebugLayer();
  //
  // 管线相关
  //
  const D3D_SHADER_MACRO* GetDebugDefines();
  //
  // 常规指令
  //
  // 创建默认缓冲区
  ComPtr<ID3D12Resource> CreateDefaultBuffer(const void* data, UINT64 data_size,
      ComPtr<ID3D12Resource>& upload_buffer);
  HRESULT LoadDDS(_In_z_ const char* szFileName,
      _Out_ ComPtr<ID3D12Resource>& texture,
      _Out_ ComPtr<ID3D12Resource>& textureUploadHeap);

private:
  // 用于DX的配置
  ikit::XmlReader config;

  // 用于管理描述符
  DxDescriptor descriptor_;
  // 用于管理根签名
  DxRootSignature rootsign_;
  // 用于管理管线
  DxPipeline pipeline_;
  // 用于管理视图
  DxView view_;
  // 用于管理绘制
  DxDraw draw_;
  // 用于初始化
  DxIniter initer_;
  // 用于Swapchain
  DxSwapchain swapchain_;
  // 用于后处理功能
  DxPostProcessing post_processing_;
  // 用于光源
  DxLights lights_;
  // 用于阴影
  DxShadows shadows_;
  // 用于Pass
  DxPass pass_;
  // 用于帧资源
  DxFrameResource frame_res_;
  // 用于UI
  DxUI ui_;
  // 用于实例精灵
  DxInstancedSprite instanced_sprite_;

  // 常规设置
  D3D_DRIVER_TYPE driver_type_ = D3D_DRIVER_TYPE_HARDWARE;

  // 标记此项目是否已经初始化
  bool is_inited_ = false;
  // 用于记录最后的鼠标位置
  POINT last_mouse_pos_;
  // 窗口句柄
  HWND hwnd_;
  // 是否使用线框模式渲染
  bool is_wire_mode_ = false;
  // 是否显示调试层
  DebugLayer show_debug_layer_ = DebugLayer::None;

  // 用于GPU波浪
  std::unique_ptr<GpuWaves> waves_ = nullptr;
  std::unique_ptr<DxMeshFactory> mesh_factory_ = nullptr;
};

} // namespace ifire::dx